#include <xen/config.h>
#include <xen/errno.h>
#include <xen/softirq.h>
+#include <asm/x86_32/asm_defns.h>
#include <public/xen.h>
-EBX = 0x00
-ECX = 0x04
-EDX = 0x08
-ESI = 0x0C
-EDI = 0x10
-EBP = 0x14
-EAX = 0x18
-DS = 0x1C
-ES = 0x20
-FS = 0x24
-GS = 0x28
-ORIG_EAX = 0x2C
-EIP = 0x30
-CS = 0x34
-EFLAGS = 0x38
-OLDESP = 0x3C
-OLDSS = 0x40
-
-/* Offsets in domain structure */
-PROCESSOR = 0
-SHARED_INFO = 4
-EVENT_SEL = 8
-EVENT_ADDR = 12
-FAILSAFE_BUFFER = 16
-FAILSAFE_SEL = 32
-FAILSAFE_ADDR = 36
-
-/* Offsets in shared_info_t */
-#define UPCALL_PENDING /* 0 */
-#define UPCALL_MASK 1
-
-/* Offsets in guest_trap_bounce */
-GTB_ERROR_CODE = 0
-GTB_CR2 = 4
-GTB_FLAGS = 8
-GTB_CS = 10
-GTB_EIP = 12
-GTBF_TRAP = 1
-GTBF_TRAP_NOCODE = 2
-GTBF_TRAP_CR2 = 4
-
-CF_MASK = 0x00000001
-IF_MASK = 0x00000200
-NT_MASK = 0x00004000
-
-#define SAVE_ALL_NOSEGREGS \
- cld; \
- pushl %gs; \
- pushl %fs; \
- pushl %es; \
- pushl %ds; \
- pushl %eax; \
- pushl %ebp; \
- pushl %edi; \
- pushl %esi; \
- pushl %edx; \
- pushl %ecx; \
- pushl %ebx; \
-
-#define SAVE_ALL \
- SAVE_ALL_NOSEGREGS \
- movl $(__HYPERVISOR_DS),%edx; \
- movl %edx,%ds; \
- movl %edx,%es; \
- movl %edx,%fs; \
- movl %edx,%gs; \
- sti;
-
#define GET_CURRENT(reg) \
movl $4096-4, reg; \
orl %esp, reg; \
ALIGN
restore_all_guest:
- # First, may need to restore %ds if clobbered by create_bounce_frame
- pushl %ss
- popl %ds
- # Second, create a failsafe copy of DS,ES,FS,GS in case any are bad
- leal DS(%esp),%esi
- leal FAILSAFE_BUFFER(%ebx),%edi
- movsl
- movsl
- movsl
- movsl
- # Finally, restore guest registers -- faults will cause failsafe
+1: movl XREGS_ds(%esp),%ds
+2: movl XREGS_es(%esp),%es
+3: movl XREGS_fs(%esp),%fs
+4: movl XREGS_gs(%esp),%gs
popl %ebx
popl %ecx
popl %edx
popl %edi
popl %ebp
popl %eax
-1: popl %ds
-2: popl %es
-3: popl %fs
-4: popl %gs
addl $4,%esp
5: iret
.section .fixup,"ax"
-10: subl $4,%esp
- pushl %gs
-9: pushl %fs
-8: pushl %es
-7: pushl %ds
-6: pushl %eax
+6: subl $4,%esp
+ pushl %eax
pushl %ebp
pushl %edi
pushl %esi
pushl %edx
pushl %ecx
pushl %ebx
- pushl %ss
- popl %ds
- pushl %ss
- popl %es
- jmp failsafe_callback
+7: SET_XEN_SEGMENTS
+ jmp failsafe_callback
.previous
.section __ex_table,"a"
.align 4
- .long 1b,6b
+ .long 1b,7b
.long 2b,7b
- .long 3b,8b
- .long 4b,9b
- .long 5b,10b
+ .long 3b,7b
+ .long 4b,7b
+ .long 5b,6b
.previous
/* No special register assumptions */
failsafe_callback:
GET_CURRENT(%ebx)
- movl PROCESSOR(%ebx),%eax
+ movl DOMAIN_processor(%ebx),%eax
shl $4,%eax
lea guest_trap_bounce(%eax),%edx
- movl FAILSAFE_ADDR(%ebx),%eax
- movl %eax,GTB_EIP(%edx)
- movl FAILSAFE_SEL(%ebx),%eax
- movw %ax,GTB_CS(%edx)
+ movl DOMAIN_failsafe_addr(%ebx),%eax
+ movl %eax,GTB_eip(%edx)
+ movl DOMAIN_failsafe_sel(%ebx),%eax
+ movw %ax,GTB_cs(%edx)
call create_bounce_frame
subl $16,%esi # add DS/ES/FS/GS to failsafe stack frame
- leal FAILSAFE_BUFFER(%ebx),%ebp
- movl 0(%ebp),%eax # DS
-FAULT1: movl %eax,(%esi)
- movl 4(%ebp),%eax # ES
-FAULT2: movl %eax,4(%esi)
- movl 8(%ebp),%eax # FS
-FAULT3: movl %eax,8(%esi)
- movl 12(%ebp),%eax # GS
-FAULT4: movl %eax,12(%esi)
- movl %esi,OLDESP(%esp)
+ movl XREGS_ds(%esp),%eax
+FAULT1: movl %eax,%gs:(%esi)
+ movl XREGS_es(%esp),%eax
+FAULT2: movl %eax,%gs:4(%esi)
+ movl XREGS_fs(%esp),%eax
+FAULT3: movl %eax,%gs:8(%esi)
+ movl XREGS_gs(%esp),%eax
+FAULT4: movl %eax,%gs:12(%esi)
+ movl %esi,XREGS_esp(%esp)
popl %ebx
popl %ecx
popl %edx
popl %edi
popl %ebp
popl %eax
- addl $20,%esp # skip DS/ES/FS/GS/ORIG_EAX
+ addl $4,%esp
FAULT5: iret
-
ALIGN
-# Simple restore -- we should never fault as we we will only interrupt ring 0
-# when sane values have been placed in all registers. The only exception is
-# NMI, which may interrupt before good values have been placed in DS-GS.
-# The NMI return code deals with this problem itself.
restore_all_xen:
popl %ebx
popl %ecx
popl %edi
popl %ebp
popl %eax
- popl %ds
- popl %es
- popl %fs
- popl %gs
addl $4,%esp
iret
ENTRY(hypercall)
pushl %eax # save orig_eax
SAVE_ALL
- GET_CURRENT(%ebx)
+ sti
+ GET_CURRENT(%ebx)
andl $(NR_hypercalls-1),%eax
call *SYMBOL_NAME(hypercall_table)(,%eax,4)
ret_from_hypercall:
- movl %eax,EAX(%esp) # save the return value
+ movl %eax,XREGS_eax(%esp) # save the return value
test_all_events:
xorl %ecx,%ecx
notl %ecx
cli # tests must not race interrupts
/*test_softirqs:*/
- movl PROCESSOR(%ebx),%eax
+ movl DOMAIN_processor(%ebx),%eax
shl $6,%eax # sizeof(irq_cpustat) == 64
test %ecx,SYMBOL_NAME(irq_stat)(%eax,1)
jnz process_softirqs
/*test_guest_events:*/
- movl SHARED_INFO(%ebx),%eax
- testb $0xFF,UPCALL_MASK(%eax)
+ movl DOMAIN_shared_info(%ebx),%eax
+ testb $0xFF,SHINFO_upcall_mask(%eax)
jnz restore_all_guest
- testb $0xFF,UPCALL_PENDING(%eax)
+ testb $0xFF,SHINFO_upcall_pending(%eax)
jz restore_all_guest
- movb $1,UPCALL_MASK(%eax) # Upcalls are masked during delivery
+ movb $1,SHINFO_upcall_mask(%eax) # Upcalls are masked during delivery
/*process_guest_events:*/
- movl PROCESSOR(%ebx),%edx
- shl $4,%edx # sizeof(guest_trap_bounce) == 16
+ movl DOMAIN_processor(%ebx),%edx
+ shl $4,%edx # sizeof(guest_trap_bounce) == 16
lea guest_trap_bounce(%edx),%edx
- movl EVENT_ADDR(%ebx),%eax
- movl %eax,GTB_EIP(%edx)
- movl EVENT_SEL(%ebx),%eax
- movw %ax,GTB_CS(%edx)
+ movl DOMAIN_event_addr(%ebx),%eax
+ movl %eax,GTB_eip(%edx)
+ movl DOMAIN_event_sel(%ebx),%eax
+ movw %ax,GTB_cs(%edx)
call create_bounce_frame
jmp restore_all_guest
call SYMBOL_NAME(do_softirq)
jmp test_all_events
-/* CREATE A BASIC EXCEPTION FRAME ON GUEST OS (RING-1) STACK: */
-/* {EIP, CS, EFLAGS, [ESP, SS]} */
-/* %edx == guest_trap_bounce, %ebx == task_struct */
-/* %eax,%ecx are clobbered. %ds:%esi contain new OLDSS/OLDESP. */
+/* CREATE A BASIC EXCEPTION FRAME ON GUEST OS (RING-1) STACK: */
+/* {EIP, CS, EFLAGS, [ESP, SS]} */
+/* %edx == guest_trap_bounce, %ebx == task_struct */
+/* %eax,%ecx are clobbered. %gs:%esi contain new XREGS_ss/XREGS_esp. */
create_bounce_frame:
- mov CS+4(%esp),%cl
+ mov XREGS_cs+4(%esp),%cl
test $2,%cl
jz 1f /* jump if returning to an existing ring-1 activation */
/* obtain ss/esp from TSS -- no current ring-1 activations */
- movl PROCESSOR(%ebx),%eax
+ movl DOMAIN_processor(%ebx),%eax
/* next 4 lines multiply %eax by 8320, which is sizeof(tss_struct) */
movl %eax, %ecx
shll $7, %ecx
addl %ecx,%eax
addl $init_tss + 12,%eax
movl (%eax),%esi /* tss->esp1 */
-FAULT6: movl 4(%eax),%ds /* tss->ss1 */
+FAULT6: movl 4(%eax),%gs /* tss->ss1 */
/* base of stack frame must contain ss/esp (inter-priv iret) */
subl $8,%esi
- movl OLDESP+4(%esp),%eax
-FAULT7: movl %eax,(%esi)
- movl OLDSS+4(%esp),%eax
-FAULT8: movl %eax,4(%esi)
+ movl XREGS_esp+4(%esp),%eax
+FAULT7: movl %eax,%gs:(%esi)
+ movl XREGS_ss+4(%esp),%eax
+FAULT8: movl %eax,%gs:4(%esi)
jmp 2f
1: /* obtain ss/esp from oldss/oldesp -- a ring-1 activation exists */
- movl OLDESP+4(%esp),%esi
-FAULT9: movl OLDSS+4(%esp),%ds
+ movl XREGS_esp+4(%esp),%esi
+FAULT9: movl XREGS_ss+4(%esp),%gs
2: /* Construct a stack frame: EFLAGS, CS/EIP */
subl $12,%esi
- movl EIP+4(%esp),%eax
-FAULT10:movl %eax,(%esi)
- movl CS+4(%esp),%eax
-FAULT11:movl %eax,4(%esi)
- movl EFLAGS+4(%esp),%eax
-FAULT12:movl %eax,8(%esi)
+ movl XREGS_eip+4(%esp),%eax
+FAULT10:movl %eax,%gs:(%esi)
+ movl XREGS_cs+4(%esp),%eax
+FAULT11:movl %eax,%gs:4(%esi)
+ movl XREGS_eflags+4(%esp),%eax
+FAULT12:movl %eax,%gs:8(%esi)
/* Rewrite our stack frame and return to ring 1. */
/* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */
andl $0xfffcbeff,%eax
- movl %eax,EFLAGS+4(%esp)
- movl %ds,OLDSS+4(%esp)
- movl %esi,OLDESP+4(%esp)
- movzwl %es:GTB_CS(%edx),%eax
- movl %eax,CS+4(%esp)
- movl %es:GTB_EIP(%edx),%eax
- movl %eax,EIP+4(%esp)
+ movl %eax,XREGS_eflags+4(%esp)
+ movl %gs,XREGS_ss+4(%esp)
+ movl %esi,XREGS_esp+4(%esp)
+ movzwl GTB_cs(%edx),%eax
+ movl %eax,XREGS_cs+4(%esp)
+ movl GTB_eip(%edx),%eax
+ movl %eax,XREGS_eip+4(%esp)
ret
-
-
+
.section __ex_table,"a"
.align 4
.long FAULT1, crash_domain_fixup3 # Fault writing to ring-1 stack
crash_domain_fixup1:
subl $4,%esp
SAVE_ALL
+ sti
jmp domain_crash
crash_domain_fixup2:
addl $4,%esp
crash_domain_fixup3:
- pushl %ss
- popl %ds
jmp domain_crash
.previous
ALIGN
process_guest_exception_and_events:
- movl PROCESSOR(%ebx),%eax
+ movl DOMAIN_processor(%ebx),%eax
shl $4,%eax
lea guest_trap_bounce(%eax),%edx
- testb $~0,GTB_FLAGS(%edx)
+ testb $~0,GTB_flags(%edx)
jz test_all_events
call create_bounce_frame # just the basic frame
- mov %es:GTB_FLAGS(%edx),%cl
+ mov GTB_flags(%edx),%cl
test $GTBF_TRAP_NOCODE,%cl
jnz 2f
subl $4,%esi # push error_code onto guest frame
- movl %es:GTB_ERROR_CODE(%edx),%eax
-FAULT13:movl %eax,(%esi)
+ movl GTB_error_code(%edx),%eax
+FAULT13:movl %eax,%gs:(%esi)
test $GTBF_TRAP_CR2,%cl
jz 1f
subl $4,%esi # push %cr2 onto guest frame
- movl %es:GTB_CR2(%edx),%eax
-FAULT14:movl %eax,(%esi)
-1: movl %esi,OLDESP(%esp)
-2: push %es # unclobber %ds
- pop %ds
- movb $0,GTB_FLAGS(%edx)
+ movl GTB_cr2(%edx),%eax
+FAULT14:movl %eax,%gs:(%esi)
+1: movl %esi,XREGS_esp(%esp)
+2: movb $0,GTB_flags(%edx)
jmp test_all_events
ALIGN
ENTRY(ret_from_intr)
GET_CURRENT(%ebx)
- movb CS(%esp),%al
+ movb XREGS_cs(%esp),%al
testb $3,%al # return to non-supervisor?
jne test_all_events
jmp restore_all_xen
pushl $ SYMBOL_NAME(do_divide_error)
ALIGN
error_code:
- pushl %fs
- pushl %es
- pushl %ds
- pushl %eax
- xorl %eax,%eax
- pushl %ebp
+ cld
+ pushl %ebp
pushl %edi
pushl %esi
pushl %edx
- decl %eax # eax = -1
pushl %ecx
pushl %ebx
- cld
- movl %gs,%ecx
- movl ORIG_EAX(%esp), %esi # get the error code
- movl GS(%esp), %edi # get the function address
- movl %eax, ORIG_EAX(%esp)
- movl %ecx, GS(%esp)
- movl $(__HYPERVISOR_DS),%edx
- movl %edx,%ds
- movl %edx,%es
- movl %edx,%fs
- movl %edx,%gs
+ movb XREGS_cs(%esp),%bl
+ testb $3,%bl
+ je 1f
+ movl %ds,XREGS_ds(%esp)
+ movl %es,XREGS_es(%esp)
+ movl %fs,XREGS_fs(%esp)
+ movl %gs,XREGS_gs(%esp)
+1: SET_XEN_SEGMENTS
+ movl XREGS_orig_eax(%esp),%esi # get the error code
+ movl XREGS_eax(%esp),%edi # get the function address
+ movl %eax,XREGS_eax(%esp)
movl %esp,%edx
pushl %esi # push the error code
pushl %edx # push the xen_regs pointer
GET_CURRENT(%ebx)
- call *%edi
+ call *%edi
addl $8,%esp
- movb CS(%esp),%al
+ movb XREGS_cs(%esp),%al
testb $3,%al
je restore_all_xen
jmp process_guest_exception_and_events
# In all other cases we bail without touching DS-GS, as we have
# interrupted an enclosing Xen activation in tricky prologue or
# epilogue code.
- movb CS(%esp),%al
+ movb XREGS_cs(%esp),%al
testb $3,%al
jne do_watchdog_tick
- movl DS(%esp),%eax
+ movl XREGS_ds(%esp),%eax
cmpw $(__HYPERVISOR_DS),%ax
- jne nmi_badseg
- movl ES(%esp),%eax
+ jne restore_all_xen
+ movl XREGS_es(%esp),%eax
cmpw $(__HYPERVISOR_DS),%ax
- jne nmi_badseg
- movl FS(%esp),%eax
+ jne restore_all_xen
+ movl XREGS_fs(%esp),%eax
cmpw $(__HYPERVISOR_DS),%ax
- jne nmi_badseg
- movl GS(%esp),%eax
+ jne restore_all_xen
+ movl XREGS_gs(%esp),%eax
cmpw $(__HYPERVISOR_DS),%ax
- jne nmi_badseg
+ jne restore_all_xen
do_watchdog_tick:
movl $(__HYPERVISOR_DS),%edx
pushl %edx # regs
call SYMBOL_NAME(do_nmi)
addl $8,%esp
- movb CS(%esp),%al
+ movb XREGS_cs(%esp),%al
testb $3,%al
je restore_all_xen
GET_CURRENT(%ebx)
jmp restore_all_guest
-nmi_badseg:
- popl %ebx
- popl %ecx
- popl %edx
- popl %esi
- popl %edi
- popl %ebp
- popl %eax
- addl $20,%esp
- iret
-
nmi_parity_err:
# Clear and disable the parity-error line
andb $0xf,%al
orb $0x4,%al
outb %al,$0x61
cmpb $'i',%ss:SYMBOL_NAME(opt_nmi) # nmi=ignore
- je nmi_badseg
+ je restore_all_xen
bts $0,%ss:SYMBOL_NAME(nmi_softirq_reason)
bts $NMI_SOFTIRQ,%ss:SYMBOL_NAME(irq_stat)
cmpb $'d',%ss:SYMBOL_NAME(opt_nmi) # nmi=dom0
- je nmi_badseg
+ je restore_all_xen
movl $(__HYPERVISOR_DS),%edx # nmi=fatal
movl %edx,%ds
movl %edx,%es
orb $0x8,%al
outb %al,$0x61
cmpb $'i',%ss:SYMBOL_NAME(opt_nmi) # nmi=ignore
- je nmi_badseg
+ je restore_all_xen
bts $1,%ss:SYMBOL_NAME(nmi_softirq_reason)
bts $NMI_SOFTIRQ,%ss:SYMBOL_NAME(irq_stat)
cmpb $'d',%ss:SYMBOL_NAME(opt_nmi) # nmi=dom0
- je nmi_badseg
+ je restore_all_xen
movl $(__HYPERVISOR_DS),%edx # nmi=fatal
movl %edx,%ds
movl %edx,%es